#ifndef __CZF_EDIT_SYNTAX_HILIGHT_CONF_H__
#define __CZF_EDIT_SYNTAX_HILIGHT_CONF_H__

#include "vararryt.h"

typedef CVarArrayT<char*> CStringArray;

#define TOKEN_INIT_COUNT 3
#define TOKEN_GROW_STEP 3

class CTokens : public CStringArray
{
public:
    CTokens();
    virtual ~CTokens();

public:
    /*  Return 0, on success: 
     *   1. adding the token if not existing. OR
     *   2. if the token already exists, do nothing.
     *  Return non-zero, on failure. possible reason is memory allocation failure.
     */
    int AddToken (const char* str);
    /* Returns true if the token is found. Returns false, if not found.
     *  No matter found or not, index is filled with the found (in case found),
     *  or closest (in case not found) token's index.
     */
    bool FindToken (const char* str, unsigned int* index);
    bool FindToken (const char* str);
    const char* GetToken(unsigned int idx);

    unsigned int m_uTokenCount;
};

class CSyntaxConfig 
{
public:
    CSyntaxConfig();
    virtual ~CSyntaxConfig();

    /* Rturns 0 on success.
     * Returns -1 on error. Typical error is memory allocation error.
     */
    int SetDelimiters (const char* s);
    int AddFileExtension (const char* s);
    int AddIndent (const char* s);
    int AddUnindent (const char* s);
    int SetBlockCommentOn (const char* s);
    int SetBlockCommentOff (const char* s);
    int SetLineComment (const char* s);
    int AddKeyword (const char* s);
    int SetEscape(const char* c);
    int SetQuote(const char* c);

public:
    CTokens     m_FileExtension;
    char*       m_Delimiter;
    CTokens     m_Indent;
    CTokens     m_Unindent;
    char*       m_BlockCommentOn;
    char*       m_BlockCommentOff;
    char*       m_LineComment;
    CTokens     m_Keywords;
    char        m_Escape;
    char*       m_Quote;
};


#define LANG_ID           1
#define FILEEXT_ID        2
#define DELIMITER_ID      3
#define INDENT_ID         4
#define UNINDENT_ID       5
#define BCOMMENTON_ID     6
#define BCOMMENTOFF_ID    7
#define LCOMMENT_ID       8
#define KEYWORD_ID        9
#define ESCCHAR_ID        10
#define QUOTE_ID          11
#define OTHER_ID          -1

#define LANG_STR            "/Language:"
#define FILEEXT_STR         "/FileExtension:"
#define DELIMITER_STR       "/Delimiters:"
#define INDENT_STR          "/IndentStrings:"
#define UNINDENT_STR        "/UnindentStrings:"
#define BCOMMENTON_STR      "/BlockCommentOn:"
#define BCOMMENTOFF_STR     "/BlockCommentOff:"
#define LCOMMENT_STR        "/LineComment:"
#define KEYWORD_STR         "/Keyword:"
#define ESCCHAR_STR         "/EscapeChar:"
#define QUOTE_STR           "/Quote:"

typedef struct tagSyntaxField 
{
    char*   txt;
    int     field_id;
} SyntaxField;

extern SyntaxField g_SyntaxFields[];

typedef CVarArrayT<CSyntaxConfig*> CSyntaxArray;
#define SYNTAX_INIT 3
#define SYNTAX_GROW 3

class CSyntaxConfigArray : public CSyntaxArray
{
public:
    CSyntaxConfigArray();
    virtual ~CSyntaxConfigArray();

    /* On success, it returns the index of newly added syntax. 
     * On error, return -1. 
     */
    int AddNewSyntax();

    /* If found, it returns the index of found CSyntaxConfig*, and *config set to the found CSyntaxConfig*
     * If not found, it returns (-1). and *config sets to NULL.
     */
    int FindSyntaxByFileExtension(const char* file_ext, CSyntaxConfig** config);

    int FindSyntaxByFilename(const char* filename, CSyntaxConfig** config);

    int ReadFromFile(const char* file);

public:
    unsigned int            m_uSyntaxCount;

protected:
    void RemoveAllSyntax();
    int ProcessLanguage(FILE* f, int* state);
    int ProcessFileExtension(FILE* f, int* state);
    int ProcessDelimiter(FILE* f, int* state);
    int ProcessIndent(FILE* f, int* state);
    int ProcessUnindent(FILE* f, int* state);
    int ProcessBlockCommentOn(FILE* f, int* state);
    int ProcessBlockCommentOff(FILE* f, int* state);
    int ProcessLineComment(FILE* f, int* state);
    int ProcessKeyword(FILE* f, int* state);
    int ProcessEscape(FILE* f, int* state);
    int ProcessQuote(FILE* f, int* state);
};

/*  Helper routines
 *  Get next word from file f, store in buf.
 *  Words are separated by white spaces (space and tab, CR and LF).
 *  On error or end of file, it returns negative value. 
 */
int GetWordFromFile(FILE* f, char* buf, size_t size);

/*  Helper routines
 *  Get string from file f, store in buf.
 *  Returns on the size-1 char, CR, LF or EOF, whatever comes first.
 */
int GetStringFromFile(FILE* f, char* buf, size_t size);

/*  Helper routines
 *  Check whether str equals one of the syntax fields specified by sf.
 *  If str matches on field str, returns the field id, otherwise returns -1 
 */
int GetSyntaxFieldsID(const SyntaxField* sf, const char* str);

#endif /* __CZF_EDIT_SYNTAX_HILIGHT_CONF_H__ */
